package com.atguigu.myjuc.callable;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

class MyThread implements Callable<String> {


    @Override
    public String call() throws Exception {
        System.out.println("MyThread");
        TimeUnit.SECONDS.sleep(3);
        return "你生来应为高山，而非草芥 .";
    }
}

/**
 *
 * 在主线程中需要执行比较耗时的操作时，但又不想阻塞主线程时，可以把这些作业交给Future对象在后台完成，
 * 当主线程将来需要时，就可以通过Future对象获得后台作业的计算结果或者执行状态。
 *
 * 一般FutureTask多用于耗时的计算，主线程可以在完成自己的任务后，再去获取结果。
 *
 * 仅在计算完成时才能检索结果；如果计算尚未完成，则阻塞 get 方法。一旦计算完成，
 * 就不能再重新开始或取消计算。get方法而获取结果只有在计算完成时获取，否则会一直阻塞直到任务转入完成状态，
 * 然后会返回结果或者抛出异常。
 *
 * 只计算一次
 * get方法放到最后
 */

/**
 * 执行流程分析：
 * 1. thread1启动 -> call()执行（3秒休眠）
 *    -> 主线程在futureTask1.get()阻塞
 *    -> call()返回 -> 打印"AAAA"
 * 2. 主线程继续执行创建thread2
 * 3. 打印"main ---over task"
 * 4. thread2启动（但程序可能立即结束）
 *
 * 典型应用场景：
 * 1. 并行计算后结果汇总
 * 2. 异步IO操作结果获取
 * 3. 任何需要分离"执行过程"和"获取结果"的场景
 */
public class CallableDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask futureTask1 = new FutureTask<>(new MyThread());
        Thread thread1 = new Thread(futureTask1,"A");
        thread1.start();
        System.out.println(futureTask1.get());
        FutureTask futureTask2 = new FutureTask<>(new MyThread());
        Thread thread2 = new Thread(futureTask2,"B");
        thread2.start();
        System.out.println(futureTask2.get());
        System.out.println(Thread.currentThread().getName()+"\t"+"===================");


    }
}
